1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.util.concurrent;
18  
19  import com.google.common.annotations.GwtCompatible;
20  import com.google.common.collect.ImmutableMap;
21  import com.google.common.collect.Sets;
22  
23  import junit.framework.TestCase;
24  
25  import java.util.Map;
26  import java.util.Random;
27  import java.util.Set;
28  
29  /**
30   * Tests for {@link AtomicLongMap}.
31   *
32   * @author mike nonemacher
33   */
34  @GwtCompatible(emulated = true)
35  public class AtomicLongMapTest extends TestCase {
36    private static final int ITERATIONS = 100;
37    private static final int MAX_ADDEND = 100;
38  
39    private Random random = new Random(301);
40  
41    public void testCreate_map() {
42      Map<String, Long> in = ImmutableMap.of("1", 1L, "2", 2L, "3", 3L);
43      AtomicLongMap<String> map = AtomicLongMap.create(in);
44      assertFalse(map.isEmpty());
45      assertSame(3, map.size());
46      assertTrue(map.containsKey("1"));
47      assertTrue(map.containsKey("2"));
48      assertTrue(map.containsKey("3"));
49      assertEquals(1L, map.get("1"));
50      assertEquals(2L, map.get("2"));
51      assertEquals(3L, map.get("3"));
52    }
53  
54    public void testIncrementAndGet() {
55      AtomicLongMap<String> map = AtomicLongMap.create();
56      String key = "key";
57      for (int i = 0; i < ITERATIONS; i++) {
58        long before = map.get(key);
59        long result = map.incrementAndGet(key);
60        long after = map.get(key);
61        assertEquals(before + 1, after);
62        assertEquals(after, result);
63      }
64      assertEquals(1, map.size());
65      assertTrue(!map.isEmpty());
66      assertTrue(map.containsKey(key));
67      assertEquals(ITERATIONS, (int) map.get(key));
68    }
69  
70    public void testIncrementAndGet_zero() {
71      AtomicLongMap<String> map = AtomicLongMap.create();
72      String key = "key";
73      assertEquals(0L, map.get(key));
74      assertFalse(map.containsKey(key));
75  
76      assertEquals(1L, map.incrementAndGet(key));
77      assertEquals(1L, map.get(key));
78  
79      assertEquals(0L, map.decrementAndGet(key));
80      assertEquals(0L, map.get(key));
81      assertTrue(map.containsKey(key));
82  
83      assertEquals(1L, map.incrementAndGet(key));
84      assertEquals(1L, map.get(key));
85    }
86  
87    public void testGetAndIncrement() {
88      AtomicLongMap<String> map = AtomicLongMap.create();
89      String key = "key";
90      for (int i = 0; i < ITERATIONS; i++) {
91        long before = map.get(key);
92        long result = map.getAndIncrement(key);
93        long after = map.get(key);
94        assertEquals(before + 1, after);
95        assertEquals(before, result);
96      }
97      assertEquals(1, map.size());
98      assertTrue(!map.isEmpty());
99      assertTrue(map.containsKey(key));
100     assertEquals(ITERATIONS, (int) map.get(key));
101   }
102 
103   public void testGetAndIncrement_zero() {
104     AtomicLongMap<String> map = AtomicLongMap.create();
105     String key = "key";
106     assertEquals(0L, map.get(key));
107     assertFalse(map.containsKey(key));
108 
109     assertEquals(0L, map.getAndIncrement(key));
110     assertEquals(1L, map.get(key));
111 
112     assertEquals(1L, map.getAndDecrement(key));
113     assertEquals(0L, map.get(key));
114     assertTrue(map.containsKey(key));
115 
116     assertEquals(0L, map.getAndIncrement(key));
117     assertEquals(1L, map.get(key));
118   }
119 
120   public void testDecrementAndGet() {
121     AtomicLongMap<String> map = AtomicLongMap.create();
122     String key = "key";
123     for (int i = 0; i < ITERATIONS; i++) {
124       long before = map.get(key);
125       long result = map.decrementAndGet(key);
126       long after = map.get(key);
127       assertEquals(before - 1, after);
128       assertEquals(after, result);
129     }
130     assertEquals(1, map.size());
131     assertTrue(!map.isEmpty());
132     assertTrue(map.containsKey(key));
133     assertEquals(-1 * ITERATIONS, (int) map.get(key));
134   }
135 
136   public void testDecrementAndGet_zero() {
137     AtomicLongMap<String> map = AtomicLongMap.create();
138     String key = "key";
139     assertEquals(0L, map.get(key));
140     assertFalse(map.containsKey(key));
141 
142     assertEquals(-1L, map.decrementAndGet(key));
143     assertEquals(-1L, map.get(key));
144 
145     assertEquals(0L, map.incrementAndGet(key));
146     assertEquals(0L, map.get(key));
147     assertTrue(map.containsKey(key));
148 
149     assertEquals(-1L, map.decrementAndGet(key));
150     assertEquals(-1L, map.get(key));
151   }
152 
153   public void testGetAndDecrement() {
154     AtomicLongMap<String> map = AtomicLongMap.create();
155     String key = "key";
156     for (int i = 0; i < ITERATIONS; i++) {
157       long before = map.get(key);
158       long result = map.getAndDecrement(key);
159       long after = map.get(key);
160       assertEquals(before - 1, after);
161       assertEquals(before, result);
162     }
163     assertEquals(1, map.size());
164     assertTrue(!map.isEmpty());
165     assertTrue(map.containsKey(key));
166     assertEquals(-1 * ITERATIONS, (int) map.get(key));
167   }
168 
169   public void testGetAndDecrement_zero() {
170     AtomicLongMap<String> map = AtomicLongMap.create();
171     String key = "key";
172     assertEquals(0L, map.get(key));
173     assertFalse(map.containsKey(key));
174 
175     assertEquals(0L, map.getAndDecrement(key));
176     assertEquals(-1L, map.get(key));
177 
178     assertEquals(-1L, map.getAndIncrement(key));
179     assertEquals(0L, map.get(key));
180     assertTrue(map.containsKey(key));
181 
182     assertEquals(0L, map.getAndDecrement(key));
183     assertEquals(-1L, map.get(key));
184   }
185 
186   public void testAddAndGet() {
187     AtomicLongMap<String> map = AtomicLongMap.create();
188     String key = "key";
189     long addend = random.nextInt(MAX_ADDEND);
190     for (int i = 0; i < ITERATIONS; i++) {
191       long before = map.get(key);
192       long result = map.addAndGet(key, addend);
193       long after = map.get(key);
194       assertEquals(before + addend, after);
195       assertEquals(after, result);
196       addend = after;
197     }
198     assertEquals(1, map.size());
199     assertTrue(!map.isEmpty());
200     assertTrue(map.containsKey(key));
201   }
202 
203   public void testAddAndGet_zero() {
204     AtomicLongMap<String> map = AtomicLongMap.create();
205     String key = "key";
206     long value = random.nextInt(MAX_ADDEND);
207     assertEquals(0L, map.get(key));
208     assertFalse(map.containsKey(key));
209 
210     assertEquals(value, map.addAndGet(key, value));
211     assertEquals(value, map.get(key));
212 
213     assertEquals(0L, map.addAndGet(key, -1 * value));
214     assertEquals(0L, map.get(key));
215     assertTrue(map.containsKey(key));
216 
217     assertEquals(value, map.addAndGet(key, value));
218     assertEquals(value, map.get(key));
219   }
220 
221   public void testGetAndAdd() {
222     AtomicLongMap<String> map = AtomicLongMap.create();
223     String key = "key";
224     long addend = random.nextInt(MAX_ADDEND);
225     for (int i = 0; i < ITERATIONS; i++) {
226       long before = map.get(key);
227       long result = map.getAndAdd(key, addend);
228       long after = map.get(key);
229       assertEquals(before + addend, after);
230       assertEquals(before, result);
231       addend = after;
232     }
233     assertEquals(1, map.size());
234     assertTrue(!map.isEmpty());
235     assertTrue(map.containsKey(key));
236   }
237 
238   public void testGetAndAdd_zero() {
239     AtomicLongMap<String> map = AtomicLongMap.create();
240     String key = "key";
241     long value = random.nextInt(MAX_ADDEND);
242     assertEquals(0L, map.get(key));
243     assertFalse(map.containsKey(key));
244 
245     assertEquals(0L, map.getAndAdd(key, value));
246     assertEquals(value, map.get(key));
247 
248     assertEquals(value, map.getAndAdd(key, -1 * value));
249     assertEquals(0L, map.get(key));
250     assertTrue(map.containsKey(key));
251 
252     assertEquals(0L, map.getAndAdd(key, value));
253     assertEquals(value, map.get(key));
254   }
255 
256   public void testPut() {
257     AtomicLongMap<String> map = AtomicLongMap.create();
258     String key = "key";
259     long newValue = random.nextInt(MAX_ADDEND);
260     for (int i = 0; i < ITERATIONS; i++) {
261       long before = map.get(key);
262       long result = map.put(key, newValue);
263       long after = map.get(key);
264       assertEquals(newValue, after);
265       assertEquals(before, result);
266       newValue += newValue;
267     }
268     assertEquals(1, map.size());
269     assertTrue(!map.isEmpty());
270     assertTrue(map.containsKey(key));
271   }
272 
273   public void testPut_zero() {
274     AtomicLongMap<String> map = AtomicLongMap.create();
275     String key = "key";
276     long value = random.nextInt(MAX_ADDEND);
277     assertEquals(0L, map.get(key));
278     assertFalse(map.containsKey(key));
279 
280     assertEquals(0L, map.put(key, value));
281     assertEquals(value, map.get(key));
282 
283     assertEquals(value, map.put(key, 0L));
284     assertEquals(0L, map.get(key));
285     assertTrue(map.containsKey(key));
286 
287     assertEquals(0L, map.put(key, value));
288     assertEquals(value, map.get(key));
289   }
290 
291   public void testPutAll() {
292     Map<String, Long> in = ImmutableMap.of("1", 1L, "2", 2L, "3", 3L);
293     AtomicLongMap<String> map = AtomicLongMap.create();
294     assertTrue(map.isEmpty());
295     assertSame(0, map.size());
296     assertFalse(map.containsKey("1"));
297     assertFalse(map.containsKey("2"));
298     assertFalse(map.containsKey("3"));
299     assertEquals(0L, map.get("1"));
300     assertEquals(0L, map.get("2"));
301     assertEquals(0L, map.get("3"));
302 
303     map.putAll(in);
304     assertFalse(map.isEmpty());
305     assertSame(3, map.size());
306     assertTrue(map.containsKey("1"));
307     assertTrue(map.containsKey("2"));
308     assertTrue(map.containsKey("3"));
309     assertEquals(1L, map.get("1"));
310     assertEquals(2L, map.get("2"));
311     assertEquals(3L, map.get("3"));
312   }
313 
314   public void testPutIfAbsent() {
315     AtomicLongMap<String> map = AtomicLongMap.create();
316     String key = "key";
317     long newValue = random.nextInt(MAX_ADDEND);
318     for (int i = 0; i < ITERATIONS; i++) {
319       long before = map.get(key);
320       long result = map.putIfAbsent(key, newValue);
321       long after = map.get(key);
322       assertEquals(before, result);
323       assertEquals(before == 0 ? newValue : before, after);
324 
325       map.remove(key);
326       before = map.get(key);
327       result = map.putIfAbsent(key, newValue);
328       after = map.get(key);
329       assertEquals(0, before);
330       assertEquals(before, result);
331       assertEquals(newValue, after);
332 
333       map.put(key, 0L);
334       before = map.get(key);
335       result = map.putIfAbsent(key, newValue);
336       after = map.get(key);
337       assertEquals(0, before);
338       assertEquals(before, result);
339       assertEquals(newValue, after);
340 
341       newValue += newValue;
342     }
343     assertEquals(1, map.size());
344     assertTrue(!map.isEmpty());
345     assertTrue(map.containsKey(key));
346   }
347 
348   public void testPutIfAbsent_zero() {
349     AtomicLongMap<String> map = AtomicLongMap.create();
350     String key = "key";
351     long value = random.nextInt(MAX_ADDEND);
352     assertEquals(0L, map.get(key));
353     assertFalse(map.containsKey(key));
354 
355     assertEquals(0L, map.putIfAbsent(key, value));
356     assertEquals(value, map.get(key));
357 
358     assertEquals(value, map.put(key, 0L));
359     assertEquals(0L, map.get(key));
360     assertTrue(map.containsKey(key));
361 
362     assertEquals(0L, map.putIfAbsent(key, value));
363     assertEquals(value, map.get(key));
364   }
365 
366   public void testReplace() {
367     AtomicLongMap<String> map = AtomicLongMap.create();
368     String key = "key";
369     long newValue = random.nextInt(MAX_ADDEND);
370     for (int i = 0; i < ITERATIONS; i++) {
371       long before = map.get(key);
372       assertFalse(map.replace(key, before + 1, newValue + 1));
373       assertFalse(map.replace(key, before - 1, newValue - 1));
374       assertTrue(map.replace(key, before, newValue));
375       long after = map.get(key);
376       assertEquals(newValue, after);
377       newValue += newValue;
378     }
379     assertEquals(1, map.size());
380     assertTrue(!map.isEmpty());
381     assertTrue(map.containsKey(key));
382   }
383 
384   public void testReplace_zero() {
385     AtomicLongMap<String> map = AtomicLongMap.create();
386     String key = "key";
387     long value = random.nextInt(MAX_ADDEND);
388     assertEquals(0L, map.get(key));
389     assertFalse(map.containsKey(key));
390 
391     assertTrue(map.replace(key, 0L, value));
392     assertEquals(value, map.get(key));
393 
394     assertTrue(map.replace(key, value, 0L));
395     assertEquals(0L, map.get(key));
396     assertTrue(map.containsKey(key));
397 
398     assertTrue(map.replace(key, 0L, value));
399     assertEquals(value, map.get(key));
400   }
401 
402   public void testRemove() {
403     AtomicLongMap<String> map = AtomicLongMap.create();
404     String key = "key";
405     assertEquals(0, map.size());
406     assertTrue(map.isEmpty());
407     assertEquals(0L, map.remove(key));
408 
409     long newValue = random.nextInt(MAX_ADDEND);
410     for (int i = 0; i < ITERATIONS; i++) {
411       map.put(key, newValue);
412       assertTrue(map.containsKey(key));
413 
414       long before = map.get(key);
415       long result = map.remove(key);
416       long after = map.get(key);
417       assertFalse(map.containsKey(key));
418       assertEquals(before, result);
419       assertEquals(0L, after);
420       newValue += newValue;
421     }
422     assertEquals(0, map.size());
423     assertTrue(map.isEmpty());
424   }
425 
426   public void testRemove_zero() {
427     AtomicLongMap<String> map = AtomicLongMap.create();
428     String key = "key";
429     assertEquals(0L, map.get(key));
430     assertFalse(map.containsKey(key));
431 
432     assertEquals(0L, map.remove(key));
433     assertEquals(0L, map.get(key));
434     assertFalse(map.containsKey(key));
435 
436     assertEquals(0L, map.put(key, 0L));
437     assertEquals(0L, map.get(key));
438     assertTrue(map.containsKey(key));
439 
440     assertEquals(0L, map.remove(key));
441     assertEquals(0L, map.get(key));
442     assertFalse(map.containsKey(key));
443   }
444 
445   public void testRemoveValue() {
446     AtomicLongMap<String> map = AtomicLongMap.create();
447     String key = "key";
448     assertEquals(0, map.size());
449     assertTrue(map.isEmpty());
450     assertFalse(map.remove(key, 0L));
451 
452     long newValue = random.nextInt(MAX_ADDEND);
453     for (int i = 0; i < ITERATIONS; i++) {
454       map.put(key, newValue);
455       assertTrue(map.containsKey(key));
456 
457       long before = map.get(key);
458       assertFalse(map.remove(key, newValue + 1));
459       assertFalse(map.remove(key, newValue - 1));
460       assertTrue(map.remove(key, newValue));
461       long after = map.get(key);
462       assertFalse(map.containsKey(key));
463       assertEquals(0L, after);
464       newValue += newValue;
465     }
466     assertEquals(0, map.size());
467     assertTrue(map.isEmpty());
468   }
469 
470   public void testRemoveValue_zero() {
471     AtomicLongMap<String> map = AtomicLongMap.create();
472     String key = "key";
473     assertEquals(0L, map.get(key));
474     assertFalse(map.containsKey(key));
475 
476     assertFalse(map.remove(key, 0L));
477     assertEquals(0L, map.get(key));
478     assertFalse(map.containsKey(key));
479 
480     assertEquals(0L, map.put(key, 0L));
481     assertEquals(0L, map.get(key));
482     assertTrue(map.containsKey(key));
483 
484     assertTrue(map.remove(key, 0L));
485     assertEquals(0L, map.get(key));
486     assertFalse(map.containsKey(key));
487   }
488 
489   public void testRemoveZeros() {
490     AtomicLongMap<Object> map = AtomicLongMap.create();
491     Set<Object> nonZeroKeys = Sets.newHashSet();
492     for (int i = 0; i < ITERATIONS; i++) {
493       Object key = new Object();
494       long value = i % 2;
495       map.put(key, value);
496       if (value != 0L) {
497         nonZeroKeys.add(key);
498       }
499     }
500     assertEquals(ITERATIONS, map.size());
501     assertTrue(map.asMap().containsValue(0L));
502 
503     map.removeAllZeros();
504     assertFalse(map.asMap().containsValue(0L));
505     assertEquals(ITERATIONS / 2, map.size());
506     assertEquals(nonZeroKeys, map.asMap().keySet());
507   }
508 
509   public void testClear() {
510     AtomicLongMap<Object> map = AtomicLongMap.create();
511     for (int i = 0; i < ITERATIONS; i++) {
512       map.put(new Object(), i);
513     }
514     assertEquals(ITERATIONS, map.size());
515 
516     map.clear();
517     assertEquals(0, map.size());
518     assertTrue(map.isEmpty());
519   }
520 
521   public void testSum() {
522     AtomicLongMap<Object> map = AtomicLongMap.create();
523     long sum = 0;
524     for (int i = 0; i < ITERATIONS; i++) {
525       map.put(new Object(), i);
526       sum += i;
527     }
528     assertEquals(ITERATIONS, map.size());
529     assertEquals(sum, map.sum());
530   }
531 
532   public void testEmpty() {
533     AtomicLongMap<String> map = AtomicLongMap.create();
534     assertEquals(0L, map.get("a"));
535     assertEquals(0, map.size());
536     assertTrue(map.isEmpty());
537     assertFalse(map.remove("a", 1L));
538     assertFalse(map.remove("a", 0L));
539     assertFalse(map.replace("a", 1L, 0L));
540   }
541 }
542